using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;
using ThaiLanguageTools.DataStruct;

namespace ThaiLanguageTools.SrcParse
{
    class LexitronFauxXmlParser : DictParser
    {
        protected override XDictHeader GetHeader()
        {
            return new XDictHeader(
                "Lexitron",
                @"http://lexitron.nectec.or.th/",
                "Free use/modify, with attribution -- This product is created by the adaptation of LEXiTRON developed by NECTEC (http://www.nectec.or.th/).");
        }

        static bool HasTag(String line, String tag)
        {
            return line.StartsWith("<" + tag) && line.EndsWith("</" + tag + ">");
        }

        static bool TryGetContents(String line, String tag, out String text, out String lang)
        {
            line = line.Trim();

            string baseTag = tag;

            // Check if the tag is there
            bool hasTag = HasTag(line, tag);
            if (!hasTag) // try thai
            { 
                tag = "t" + baseTag;
                hasTag = HasTag(line, tag); 
            }
            if (!hasTag) // try english
            {
                tag = "e" + baseTag;
                hasTag = HasTag(line, tag);
            }
            if (!hasTag) 
            {
                text = null;
                lang = null;
                return false; 
            }

            // chop off the tag
            text = line.Substring(2 + tag.Length, line.Length - (5 + 2 * tag.Length));
            text = text.Trim();

            if (tag.StartsWith("t")) { lang = Language.Thai; }
            else { lang = Language.English; }

            return true;
        }

        override protected XDictEntry ParseEntry(StreamReader sr)
        {
            const String doc = "Doc";

            const String te_search = "search"; // word itself
            const String te_entry = "entry"; // translation, usually same as search
            const String te_cat = "cat"; // POS
            const String te_syn = "syn";  // synonyms
            const String te_ant = "ant";  // antonyms
            const String te_sample = "sample"; // usage sample
            const String te_def = "def"; // no idea how is this different from tenglish/ethai 
            const String te_num = "num"; // not sure what it is, some thai grammatical category?

            // Special cases
            const String tenglish = "tenglish"; //  enlgish translation (lang=en !!!)
            const String ethai = "ethai"; // thai translation (lang=th !!!)
            const String notes = "notes"; // freeform, usually thai
            const String id = "id"; // ignore

            XDictEntry entry = null;

            while (true)
            {
                String line = sr.ReadLine();
                if (line == null) { return null; } // EOF
                line = line.Trim();

                String text;
                String lang;

                if (line == "</" + doc + ">") { return entry; } // end tag
                else if (line == "<" + doc + ">") { /* do nothing */ }
                else if (line.StartsWith("<" + id + ">")) { /* do nothing */ }
                else if (line == "") { /* do nothing */ }
                else if (TryGetContents(line, te_search, out text, out lang))
                {
                    entry = new XDictEntry(new XWordInfo(text, lang));
                }
                else
                {
                    if (entry == null)
                    {
                        entry = new XDictEntry(new XWordInfo("!!!error!!!", Language.English));
                        Console.WriteLine("    WARNING: No entry in at line: " + line);
                    }

                    if (TryGetContents(line, te_entry, out text, out lang))
                    {
                        // Prevent duplication
                        if (entry.Word.Text != text || entry.Word.Language != lang)
                        {
                            entry.Translations.Add(new XWordInfo(text, lang));
                        }
                    }
                    else if (TryGetContents(line, te_cat, out text, out lang))
                    {
                        entry.Word.PartOfSpeech = text;
                    }
                    else if (TryGetContents(line, te_syn, out text, out lang))
                    {
                        entry.Synonyms.Add(new XWordInfo(text, lang));
                    }
                    else if (TryGetContents(line, te_ant, out text, out lang))
                    {
                        entry.Antonyms.Add(new XWordInfo(text, lang));
                    }
                    else if (TryGetContents(line, te_sample, out text, out lang))
                    {
                        entry.Samples.Add(new XWordInfo(text, lang));
                    }
                    else if (TryGetContents(line, te_num, out text, out lang))
                    {
                        entry.Classifier = text;
                    }
                    else if (TryGetContents(line, te_def, out text, out lang))
                    {
                        entry.Definitions.Add(new XWordInfo(text, lang));
                    }
                    else if (TryGetContents(line, tenglish, out text, out lang))
                    {
                        // Always en
                        String[] words = text.Split(';');
                        foreach (String w in words)
                        {
                            entry.Translations.Add(new XWordInfo(w.Trim(), Language.English));
                        }
                    }
                    else if (TryGetContents(line, ethai, out text, out lang))
                    {
                        // Always th
                        String[] words = text.Split(',');
                        foreach (String w in words)
                        {
                            entry.Translations.Add(new XWordInfo(w.Trim(), Language.Thai));
                        }
                    }
                    else if (TryGetContents(line, notes, out text, out lang))
                    {
                        // Always th
                        entry.Comments.Add(new XWordInfo(text, Language.Thai));
                    }
                    else
                    {
                        Debug.Assert(false, "Unknown tag: " + line);
                    }
                }
            }
        }

    }
}
